<template>
  <div class="file-upload">
    <button class="upload-button" @click="triggerFileInput">上传</button>
    <ul class="file-list">
      <li v-for="file in files" :key="file.fileName" class="file-item">
        <span class="file-name">{{ file.fileName }}</span>
        <Space>
          <Button type="link" @click="handlePreview(file)">预览</Button>
          <Button type="link" @click="handleDownload(file.fileUrl)">下载</Button>
          <button class="delete-button" @click="removeFile(file)">删除</button>
        </Space>
      </li>
    </ul>
    <input
      type="file"
      class="file-input"
      ref="fileInput"
      @change="handleFileChange"
      multiple
      accept=".ppt,.pptx,.doc,.docx,.xls,.xlsx,.pdf,.jpg,.jpeg,.png,.zip,.mp3,.mp4"
      style="display: none;"
    />

    <!-- 模态框 -->
    <a-modal
      v-model:visible="isModalVisible"
      title="文件预览"
      @cancel="isModalVisible = false"
      :width="800"
      :style="{ top: '20px' }"
      footer=""
    >
      <img v-if="isImage(previewUrl)" :src="previewUrl" alt="预览" style="width: 100%; max-height: 500px; object-fit: contain;" />
      <iframe v-else-if="isPdf(previewUrl)" :src="previewUrl" style="width: 100%; height: 500px;" frameborder="0"></iframe>
      <p v-else>无法预览此文件类型</p>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue'
import { message } from 'ant-design-vue'
import { ossApi } from '@/api/modules/oss'
import type { OssTokenVO } from '@/types/oss'

interface UploadFile {
  fileName: string;
  fileUrl: string;
  fileSize: number;
  fileType: string;
}

const emit = defineEmits(['update:value'])
const files = ref<UploadFile[]>([])
const fileInput = ref<HTMLInputElement | null>(null)
const isModalVisible = ref(false) // 控制模态框的显示
const previewUrl = ref('') // 存储预览的文件 URL

// 1. 组件 props 的 value
const props = defineProps<{
  value?: UploadFile[]
}>()

// 2. 监听 props 变化
watch(() => props.value, (newValue) => {
  console.log('Props value changed:', newValue)
  if (newValue) {
    files.value = newValue
  }
}, { immediate: true })

const triggerFileInput = () => {
  fileInput.value?.click()
}

const handleFileChange = async (event: Event) => {
  const input = event.target as HTMLInputElement
  if (!input.files?.length) return

  try {
    // 3. 上传前的文件列表
    console.log('Before upload files:', files.value)
    
    const uploadedFiles = await Promise.all(
      Array.from(input.files).map(uploadFile)
    )
    
    files.value = [...files.value, ...uploadedFiles.filter((file): file is UploadFile => file !== null)]
    // 4. 上传后的文件列表
    console.log('After upload files:', files.value)
    emit('update:value', files.value)
    
    input.value = ''
  } catch (error) {
    console.error('文件上传失败:', error)
    message.error('文件上传失败')
  }
}

const uploadFile = async (file: File): Promise<UploadFile | null> => {
  try {
    // 获取上传凭证
    const ossData = await ossApi.getToken('files/')
    const fileName = generateFileName(file)
    const key = `${ossData.dir}${fileName}`

    // 创建 FormData
    const formData = new FormData()
    formData.append('key', key)
    formData.append('file', file)
    Object.entries({
      policy: ossData.policy,
      OSSAccessKeyId: ossData.accessKeyId,
      success_action_status: '200',
      signature: ossData.signature,
      'x-oss-security-token': ossData.securityToken
    }).forEach(([name, value]) => {
      formData.append(name, value as string)
    })

    // 上传文件
    const response = await fetch(ossData.host, {
      method: 'POST',
      body: formData,
      mode: 'cors',
    })

    if (!response.ok) {
      const errorText = await response.text()
      throw new Error(errorText)
    }

    // 返回文件信息
    return {
      fileName: file.name,
      fileUrl: `${ossData.host}/${key}`,
      fileSize: file.size,
      fileType: file.type
    }
  } catch (error) {
    console.error('文件上传失败:', error)
    message.error(`文件 ${file.name} 上传失败`)
    return null
  }
}

const generateFileName = (file: File): string => {
  const ext = file.name.substring(file.name.lastIndexOf('.'))
  const timestamp = new Date().getTime()
  const random = Math.floor(Math.random() * 1000)
  return `${timestamp}_${random}${ext}`
}

const removeFile = (file: UploadFile) => {
  // 5. 删除文件前的列表
  console.log('Before remove file:', files.value)
  files.value = files.value.filter(f => f.fileName !== file.fileName)
  // 6. 删除文件后的列表
  console.log('After remove file:', files.value)
  emit('update:value', files.value)
}

// 预览文件
const handlePreview = (file: UploadFile) => {
  previewUrl.value = file.fileUrl // 设置预览 URL
  isModalVisible.value = true // 显示模态框
}

// 下载文件
const handleDownload = (fileUrl: string) => {
  const link = document.createElement('a')
  link.href = fileUrl
  link.download = fileUrl.split('/').pop() || '下载文件'
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}

// 判断文件类型
const isImage = (url: string) => {
  return /\.(jpg|jpeg|png|gif)$/i.test(url)
}

const isPdf = (url: string) => {
  return /\.pdf$/i.test(url)
}
</script>

<style scoped>
.file-upload {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.upload-button {
  background-color: #1890ff;
  color: white;
  border: none;
  padding: 10px;
  border-radius: 4px;
  cursor: pointer;
}

.file-list {
  list-style: none;
  padding: 0;
}

.file-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px;
  border: 1px solid #e8e8e8;
  border-radius: 4px;
  margin-top: 5px;
}

.file-name {
  color: #333;
}

.delete-button {
  background-color: transparent;
  border: none;
  color: #ff4d4f;
  cursor: pointer;
}
</style>